package dubbo.learn.common.spi;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.*;

@Slf4j
public class SpiParser {
    private static final String PREFIX = "META-INF/mini-dubbo/";


    public static String getSpiForSpecifiedService(Class<?> clazz) {
        String fullName = PREFIX + clazz.getName();
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        List<URL> list;
        try {
            Enumeration<URL> configs = classLoader.getResources(fullName);
            URL[] urls = CollectionUtils.toArray(configs, new URL[]{});
            list = CollectionUtils.arrayToList(urls);
        } catch (IOException e) {
            log.error("parse file failed.{},e:{}",fullName,e);
            return null;
        }
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }

        HashSet<String> serviceNames = new HashSet<>();
        for (URL url : list) {
            List<String> listInTheUrl = parse(url);
            serviceNames.addAll(listInTheUrl);
        }

        if (CollectionUtils.isEmpty(serviceNames)) {
            return null;
        }
        log.info("get origin spi service list:{}",serviceNames);

        /**
         * 去除掉没在类路径里的
         */
        serviceNames.removeIf(serviceName -> {
            try {
                classLoader.loadClass(serviceName);
                return false;
            } catch (ClassNotFoundException e) {
                log.error("e:{}",e);
                return true;
            }
        });
        log.info("get final spi service list:{},remove those not in classpath",
                serviceNames);
        if (CollectionUtils.isEmpty(serviceNames)) {
            return null;
        }

        return serviceNames.iterator().next();
    }


    private static List<String> parse(URL url)
            throws ServiceConfigurationError
    {
        ArrayList<String> names = new ArrayList<>();
        try(InputStream in = url.openStream();
            BufferedReader bufferedReader =
                    new BufferedReader(new InputStreamReader(in, "utf-8"))) {
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(line)) {
                    continue;
                }
                names.add(line);
            }
        } catch (IOException x) {
            log.error("e:{}",x);
            return new ArrayList<>();
        }

        return names;
    }


}
